package br.com.healthapplet.applet;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Label;
import java.util.concurrent.LinkedBlockingQueue;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JLabel;
import javax.swing.JPanel;

import br.com.healthapplet.util.Constants;
import br.com.healthapplet.util.EncodeUtil;
import br.com.healthapplet.util.ImageUtil;
import br.com.healthapplet.util.ServerUtil;

import com.digitalpersona.onetouch.DPFPDataPurpose;
import com.digitalpersona.onetouch.DPFPFeatureSet;
import com.digitalpersona.onetouch.DPFPFingerIndex;
import com.digitalpersona.onetouch.DPFPGlobal;
import com.digitalpersona.onetouch.DPFPSample;
import com.digitalpersona.onetouch.DPFPTemplate;
import com.digitalpersona.onetouch.capture.DPFPCapture;
import com.digitalpersona.onetouch.capture.DPFPCapturePriority;
import com.digitalpersona.onetouch.capture.event.DPFPDataEvent;
import com.digitalpersona.onetouch.capture.event.DPFPDataListener;
import com.digitalpersona.onetouch.capture.event.DPFPReaderStatusAdapter;
import com.digitalpersona.onetouch.capture.event.DPFPReaderStatusEvent;
import com.digitalpersona.onetouch.processing.DPFPEnrollment;
import com.digitalpersona.onetouch.processing.DPFPFeatureExtraction;

public class RegisterApplet extends JApplet{
	
	private static final long serialVersionUID = -8366442351831742255L;
	
	private Label appletLabel;
	
	private LinkedBlockingQueue<DPFPSample> samples;
	
	private DPFPFeatureSet featureSet;
	
	private DPFPFingerIndex finger;
	
	private String pacienteId;
	
	private JLabel picture;
	
	private JPanel center;
	
	private ImageUtil imageUtil;
	
	private EncodeUtil encoder;
	
	private ServerUtil serverUtil;
	
	private DPFPFeatureExtraction featureExtractor;
	
	private DPFPEnrollment enrollment;
	
	public void init() {
		featureExtractor = DPFPGlobal
				.getFeatureExtractionFactory().createFeatureExtraction();
		enrollment = DPFPGlobal.getEnrollmentFactory()
				.createEnrollment();
		
		pacienteId = getParameter("pacienteId");
		picture = new JLabel();
		center = new JPanel(new BorderLayout());
		imageUtil = new ImageUtil();
		encoder = new EncodeUtil();
		serverUtil = new ServerUtil();
		finger = DPFPFingerIndex.RIGHT_INDEX;
		samples = new LinkedBlockingQueue<DPFPSample>();
		appletLabel = new Label();
		
		picture.setBorder(BorderFactory.createLoweredBevelBorder());
		picture.setPreferredSize(new Dimension(350, 280));
		
		appletLabel.setText("Coloque o dedo indicador da mao direita no leitor.");
		
		center.setBackground(Color.GRAY);
		center.add(picture, BorderLayout.NORTH);
		center.add(appletLabel, BorderLayout.SOUTH);
		
		add(center);
	}
	
	public void start(){
		
		try{
			
			while (enrollment.getFeaturesNeeded() > 0) {
				DPFPSample sample = getSample();
				
				String appletString = String.format("Faltam %d leituras", 
						enrollment.getFeaturesNeeded()-1);
				
				appletLabel.setText(appletString);
				
				drawPicture(imageUtil.convertSampleToBitmap(sample));
				
				try {
					featureSet = featureExtractor.createFeatureSet(sample,
							DPFPDataPurpose.DATA_PURPOSE_ENROLLMENT);
					enrollment.addFeatures(featureSet);
				} catch (Exception e) {
					e.getStackTrace();
					appletLabel.setText("Tente novamente.");
					stop();
				}				
			}
			
			DPFPTemplate template = enrollment.getTemplate();
			
			String templateString = encoder.encodeBytes(template.serialize());

			boolean verify = serverUtil.callRegisterServicewithPostMethod(finger.toString(), pacienteId, templateString, Constants.URL_NAME_REGISTER);

			if(verify){
				appletLabel.setText("Biometria capturada com sucesso.");
			} else {
				appletLabel.setText("Erro.");
				stop();
			}
			
			stop();
			
		} catch (Exception e) {
			e.getStackTrace();
			appletLabel.setText("Erro ao capturar a biometria.");
			stop();
		}
	}
	
	public void stop(){
		destroy();
	}
	
	private void drawPicture(Image image) {
		picture.setIcon(new ImageIcon(
			image.getScaledInstance(picture.getWidth(), picture.getHeight(), Image.SCALE_DEFAULT)));
	}
	
	private DPFPSample getSample() throws Exception {
		
		DPFPCapture capture = DPFPGlobal.getCaptureFactory().createCapture();
		
		capture.setPriority(DPFPCapturePriority.CAPTURE_PRIORITY_LOW);
		
		capture.addDataListener(new DPFPDataListener() {
			public void dataAcquired(DPFPDataEvent e) {
				if (e != null && e.getSample() != null) {
					try {
						samples.put(e.getSample());
					} catch (Exception e1) {
						e1.printStackTrace();
						stop();
					}
				}
			}
		});
		
		capture.addReaderStatusListener(new DPFPReaderStatusAdapter() {
			int lastStatus = DPFPReaderStatusEvent.READER_CONNECTED;

			public void readerConnected(DPFPReaderStatusEvent e) {
				if (lastStatus != e.getReaderStatus())
				lastStatus = e.getReaderStatus();
			}

			public void readerDisconnected(DPFPReaderStatusEvent e) {
				if (lastStatus != e.getReaderStatus()){
					appletLabel.setText("O leitor esta desconectado.");
				}
				lastStatus = e.getReaderStatus();
			}

		});
		
		try {
			capture.startCapture();
			return samples.take();
		} catch (Exception e) {
			appletLabel.setText("Falha ao iniciar captura.");
			stop();
			throw e;
		} finally {
			capture.stopCapture();
		}
	}
	
}